<?php

namespace cccmvc;

use cccmvc\exception\NotFoundException;

class Router
{
    protected array $routes = [];
    protected Request $request;
    protected Response $response;

    public function __construct(Request $request, Response $response)
    {
        $this->request = $request;
        $this->response = $response;
    }

    public function get($path, $callback)
    {
        $this->routes['GET'][$path] = $callback;
    }

    public function post($path, $callback)
    {
        $this->routes["POST"][$path] = $callback;
    }

    /**
     * @throws NotFoundException
     */
    public function resolve()
    {
        $method = $this->request->getMethod();
        $path = sprintf("/%s", ltrim($this->request->getPath(), '/'));

        // Get callable or class from path
        $callback = $this->getCallableFromPath($path);

        echo $callback($this->request, $this->response);
        die;
    }

    private function getCallableFromPath($path)
    {
        $path = sprintf('/%s', ltrim($path, '/'));

        // Named route.
        if ($callback = $this->routes[$this->request->getMethod()][$path]) {
            if (is_array($callback)) {
                $controller = $callback[0];
                $action = $callback[1];

                return function () use ($controller, $action) {
                    $instance = new $controller();

                    return $instance->$action($this->request, $this->response);
                };
            } else {
                if (is_callable($callback)) {
                    return $callback;
                }
            }
            return;
        }

        $arr = explode('/', ltrim($path, '/'));
        $controller = ucfirst($arr[0]) . "Controller";
        $action = $arr[1];
        $params = array_slice($arr, 2);
        $controller = Application::$appNamespace . '\\controllers\\' . $controller;

        $instance = new $controller();

        if (!method_exists($controller, $action)) {
            throw new NotFoundException();
        }

        return function () use ($instance, $action, $params) {
            return $instance->$action($this->request, $this->response, ...$params);
        };
    }
}